<template>
	<slot name="defualt">
		<el-button type="primary" icon="ele-Download"  @click="open">导入</el-button>
	</slot>
	<!-- 导入弹框 -->
	<el-dialog ref="dialogRef" v-model="showDialog" title="导入" :width="550" :close-on-click-modal="false" append-to-body destroy-on-close>
		<el-progress v-if="loading" :text-inside="true" :stroke-width="20" :percentage="percentage" style="margin-bottom: 15px" />
		<div v-loading="loading">
			<el-upload
				ref="uploadRef"
				drag
				:accept="accept"
				:maxSize="maxSize"
				:limit="1"
				:data="params"
				:show-file-list="false"
				:http-request="request"
				:before-upload="before"
				:on-progress="progress"
				:on-success="success"
				:on-error="error"
			>
				<slot name="uploader">
					<el-icon class="el-icon--upload">
						<SvgIcon name="ele-UploadFilled" :size="80" />
					</el-icon>
					<div class="el-upload__text">将文件拖到此处或 <em>点击选择文件上传</em></div>
				</slot>
				<template #tip>
					<div class="el-upload__tip">
						<template v-if="tip">{{ tip }}</template>
						<template v-else>请上传小于或等于 {{ maxSize }}M 的 {{ accept }} 格式文件</template>
						<p v-if="templateUrl" style="margin-top: 7px">
							<el-link :href="templateUrl" target="_blank" type="primary" :underline="false">下载导入模板</el-link>
						</p>
					</div>
				</template>
			</el-upload>
			<el-form v-if="$slots.form" inline label-width="100px" label-position="left" style="margin-top: 18px">
				<slot name="form" :formData="formData"></slot>
			</el-form>
		</div>
	</el-dialog>

	<!-- 错误弹框 -->
	<el-dialog
		v-model="errShowDialog"
		title="导入失败"
		:width="660"
		destroy-on-close
		@closed="
			() => {
				errorData.data = {};
			}
		"
	>
		<div style="margin-top: 15px">
			<slot name="errTable" :errorData="errorData">
				<el-alert
					:title="`总共 ${errorData.total_count} 条，其中有 ${errorData.fail_count} 条格式不满足导入要求，请修改后再次操作！`"
					type="error"
					show-icon
					:closable="false"
				/>
				<el-table :data="errorData.data" max-height="270" style="width: 100%">
					<el-table-column prop="key" label="键名" width="150" />
					<el-table-column prop="row_count" label="行数" width="100" />
					<el-table-column prop="" label="状态" width="100">
						<el-tag type="danger"><SvgIcon name="ele-CircleCloseFilled" :size="12" /> 失败</el-tag>
					</el-table-column>
					<el-table-column prop="reason" label="原因" />
				</el-table>
			</slot>
		</div>
		<template #footer>
			<el-button type="primary" @click="errShowDialog = false">关闭</el-button>
		</template>
	</el-dialog>
</template>

<script lang="ts" setup>
import { ref, reactive } from 'vue';
import { messageError, messageSuccess } from '/@/utils/message';
import type { UploadInstance } from 'element-plus';

const props = defineProps({
	// 接口参数
	params: {
		type: Object,
		required: true,
		default: () => ({}),
	},
	// 导入文件类型
	accept: {
		type: String,
		default: '.xlsx,.xls',
	},
	// 最大导入大小，单位M
	maxSize: {
		type: Number,
		default: 10,
	},
	// 方法
	fetchFun: {
		type: Function,
		required: true,
	},
	// 提示文字
	tip: {
		type: String,
		default: '',
	},
	// 下载模板路径
	templateUrl: {
		type: String,
		default: '',
	},
});

const dialogRef = ref(null);

const uploadRef = ref<UploadInstance>();

const showDialog = ref(false);

const loading = ref(false);

const percentage = ref(0);

const formData = reactive({});

const emit = defineEmits(['success']);

const errShowDialog = ref(false);

const errorData = reactive({
	data: {},
	total_count: 0,
	fail_count: 0,
});

const open = () => {
	showDialog.value = true;
	percentage.value = 0;
};

const close = () => {
	showDialog.value = false;
};

const errOpen = (data) => {
	if (data?.error_data) errorData.data = data.error_data;
	if (data?.total_count) errorData.total_count = data.total_count;
	if (data?.fail_count) errorData.fail_count = data.fail_count;
	errShowDialog.value = true;
};

const before = (file: any, fileLists: any[]) => {
	const maxSize = file.size / 1024 / 1024 < props.maxSize;
	if (!maxSize) {
		messageError(`上传文件大小不能超过 ${props.maxSize}M!`);
		return false;
	}
	let fileType = file.name.split('.').pop();
	let acceptArr = props.accept.split('.').join('').split(',');
	if (!acceptArr.includes(fileType.substring(fileType.lastIndexOf('/') + 1, fileType.length))) {
		messageError('上传文件格式不符！');
		fileLists.splice(-1, 1);
		return false;
	}
	loading.value = true;
};

const progress = (event: any) => {
	percentage.value = parseInt(event.percent);
};

const success = (response: any, file: any) => {
	uploadRef.value?.clearFiles();
	uploadRef.value?.handleRemove(file);
	loading.value = false;
	percentage.value = 0;
	close();
	if(response.data?.status == 'success') {
		messageSuccess('导入成功，总共' + response.data.success_count + '条')
		emit('success', response.data);
	} else {
		errOpen(response.data);
	}
};

const error = (err: any) => {
	loading.value = false;
	percentage.value = 0;
};

const request = (param) => {
	Object.assign(param.data, formData);
	const data = new FormData();
	data.append(param.filename, param.file);
	for (const key in param.data) {
		data.append(key, param.data[key]);
	}

	props
		.fetchFun(data, {
			callback: (type: string, e: any) => {
				let complete = e.progress * 100;
				param.onProgress({ percent: complete });
			},
		})
		.then((res) => {
			param.onSuccess(res);
		})
		.catch((err) => {
			param.onError(err);
		});
};
defineExpose({
	open,
});
</script>

<style>
</style>
